﻿using ICSharpCode.SharpZipLib.Zip;
using Microsoft.SharePoint.Client;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Text;
using System.Xml;

namespace Futajma.MigrationStudio.SharePointPersistance
{
    public class Utils
    {
        public static void CopyStream(Stream source, Stream destination)
        {

            byte[] buffer = new byte[32768];

            int bytesRead;

            do
            {

                bytesRead = source.Read(buffer, 0, buffer.Length);

                destination.Write(buffer, 0, bytesRead);

            } while (bytesRead != 0);

        }

        private static string CheckOrCreateApplicationFolder()
        {
            string appFolder = Path.GetTempPath() + "MappingTool";

            if (!System.IO.Directory.Exists(appFolder))
            {
                Directory.CreateDirectory(appFolder);
            }
            return appFolder;
        }

        public static ListItem GetFileFromFolder(ClientContext clientContext, int folderId, string filename, string listTitle)
        {

            Web oWebsite = clientContext.Web;
            ListCollection collList = oWebsite.Lists;

            List oList = collList.GetByTitle(listTitle);

            ListItem item = oList.GetItemById(folderId);
            clientContext.Load(oList);
            clientContext.Load(item);
            clientContext.ExecuteQuery();

            var file = GetFolderItem(clientContext, (string)item["FileRef"], oList, filename, listTitle);

            return file;
        }

        public static bool CheckIfItemIsValid(int itemId, string listTitle, string camlQuery)
        {
            ExtendedClientContext clientContext = new ExtendedClientContext(Settings.MigrationPortalUrl);

            Web oWebsite = clientContext.Web;
            ListCollection collList = oWebsite.Lists;

            List oList = collList.GetByTitle(listTitle);

            CamlQuery query = new CamlQuery();
           
            //query.ViewXml = string.Format("<View><Query><Where><And><Eq><FieldRef Name='ID'/><Value Type='Number'>{0}</Value></Eq>"
            //    + "<Eq><FieldRef Name='Status'/><Value Type='Choice'>Mapping Started</Value></Eq></And></Where></Query></View>", itemId);
            query.ViewXml = string.Format(camlQuery, itemId);
            var items = oList.GetItems(query);
            clientContext.Load(items);
            clientContext.ExecuteQuery();

            return items.Count > 0;
        }

        public static ListItem GetFolderItem(ClientContext clientContext, string folderServerRelativeUrl, List list, string fileName, string listTitle)
        {
            Web oWebsite = clientContext.Web;
            ListCollection collList = oWebsite.Lists;

            List oList = collList.GetByTitle(listTitle);

            var query = new CamlQuery();

            query.FolderServerRelativeUrl = folderServerRelativeUrl;

            query.ViewXml = "<View Scope=\"RecursiveAll\"> " +
                "<Query>" +
                "<Where>" +
                 "<And>" +
                            "<Eq>" +
                                "<FieldRef Name=\"FileDirRef\" />" +
                                "<Value Type=\"Text\">" + folderServerRelativeUrl + "</Value>" +
                            "</Eq>" +
                            "<Eq>" +
                                "<FieldRef Name=\"FileLeafRef\" />" +
                                "<Value Type=\"Text\">" + fileName + "</Value>" +
                             "</Eq>" +
                 "</And>" +
                "</Where>" +
                "</Query>" +
                "</View>";

            var folderItems = list.GetItems(query);
            clientContext.Load(folderItems);
            clientContext.ExecuteQuery();

            if (folderItems.Count > 0)
            {
                return folderItems[0];
            }

            return null;
        }

        public static ListItem GetFolder(ClientContext clientContext, int folderId, string listTitle)
        {
            Web oWebsite = clientContext.Web;
            ListCollection collList = oWebsite.Lists;

            List oList = collList.GetByTitle(listTitle);
            ListItem item = oList.GetItemById(folderId);
            clientContext.ExecuteQuery();

            return item;
        }


        public static string LoadZipFileAndExtractToUserFolder(string fileName, int folderId)
        {
            ExtendedClientContext clientContext = new ExtendedClientContext(Settings.MigrationPortalUrl);

            var folderPath = string.Format(@"{0}\{1}", CheckOrCreateApplicationFolder(), Path.GetRandomFileName());

            Directory.CreateDirectory(folderPath);

            var val = GetFileFromFolder(clientContext, folderId, fileName, Settings.MigrationListTitle);

            if (val != null)
            {
                var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, (string)val["FileRef"]);

                if (fileInfo != null && fileInfo.Stream != null)
                {
                    using (var stream = new MemoryStream())
                    {
                        CopyStream(fileInfo.Stream, stream);
                        stream.Seek(0, SeekOrigin.Begin);

                        FastZip fz = new FastZip();
                        fz.ExtractZip(stream, folderPath, FastZip.Overwrite.Always, null, null, null, true, false);
                    }
                }
                else
                {
                    return null;
                }


                //if (fileInfo != null && fileInfo.Stream != null)
                //{
                //    using (var stream = System.IO.File.OpenWrite(string.Format(@"{0}\{1}", folderPath, fileName)))
                //    {
                //        CopyStream(fileInfo.Stream, stream);
                //        stream.Flush();
                //    }
                //}

                //ExtractFiles(string.Format(@"{0}\{1}", folderPath, fileName));
                return folderPath;
            }
            else
            {
                return null;
            }
        }

        public static void SaveFileToFolder(Stream fileStream, string fileName, int folderId, string listTitle)
        {
            ExtendedClientContext clientContext = new ExtendedClientContext(Settings.MigrationPortalUrl);

            string url = "";
            var item = GetFileFromFolder(clientContext, folderId, fileName, listTitle);


            if (item == null)
            {
                var folder = GetFolder(clientContext, folderId, listTitle);
                url = string.Format("{0}/{1}", (string)folder["FileRef"], fileName);
            }
            else
            {
                url = (string)item["FileRef"];
            }

             Microsoft.SharePoint.Client.File.SaveBinaryDirect(clientContext, url, fileStream, true);
        }

        public static Stream GetFileFromFolder(string fileName, int folderId, string listTitle, out int fileSize)
        {
            ExtendedClientContext clientContext = new ExtendedClientContext(Settings.MigrationPortalUrl);
          
            var val = GetFileFromFolder(clientContext, folderId, fileName, listTitle);
            fileSize = 0;
            if (val != null)
            {
                fileSize = int.Parse((string)val["File_x0020_Size"]);
                var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, (string)val["FileRef"]);

                if (fileInfo != null && fileInfo.Stream != null)
                {
                    return fileInfo.Stream;
                }

            }
            return null;
        }

        public static string GetAppSetting(string key)
        {
            return ConfigurationManager.AppSettings[key];
            //string exeConfigPath = typeof(SharePoint2010ApplicationConfiguration).Assembly.Location;

            //var config = ConfigurationManager.OpenExeConfiguration(exeConfigPath);

            //KeyValueConfigurationElement element = config.AppSettings.Settings[key];
            //if (element != null)
            //{
            //    string value = element.Value;
            //    if (!string.IsNullOrEmpty(value))
            //        return value;
            //}
            //return string.Empty;
        }
    }
}
